home *** CD-ROM | disk | FTP | other *** search
/ Network PC / Network PC.iso / amiga utilities / communication / bbs / termv4.6 / extras / source / term-source.lha / CustomRequest.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-18  |  18.1 KB  |  769 lines

  1. /*
  2. **    CustomRequest.c
  3. **
  4. **    EasyRequest like custom requester
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* GetScreenInfo():
  17.      *
  18.      *    Obtain the currently visible screen area.
  19.      */
  20.  
  21. STATIC VOID
  22. GetScreenInfo(struct Screen *Screen,WORD *Left,WORD *Top,WORD *Width,WORD *Height)
  23. {
  24.     struct ViewPortExtra    *Extra;
  25.     struct TagItem             Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
  26.  
  27.     if(!VideoControl(Screen -> ViewPort . ColorMap,Tags))
  28.         Extra = (struct ViewPortExtra *)Tags[0] . ti_Data;
  29.     else
  30.         Extra = NULL;
  31.  
  32.     if(!Extra)
  33.         Extra = Screen -> ViewPort . ColorMap -> cm_vpe;
  34.  
  35.     if(!Extra)
  36.         Extra = (struct ViewPortExtra *)GfxLookUp(&Screen -> ViewPort);
  37.  
  38.     if(Extra)
  39.     {
  40.         struct Rectangle Clip;
  41.  
  42.         QueryOverscan(GetVPModeID(&Screen -> ViewPort),&Clip,OSCAN_TEXT);
  43.  
  44.         *Width    = Extra -> DisplayClip . MaxX - Extra -> DisplayClip . MinX + 1;
  45.         *Height    = Extra -> DisplayClip . MaxY - Extra -> DisplayClip . MinY + 1;
  46.  
  47.         if(*Width < Clip . MaxX - Clip . MinX + 1)
  48.             *Width = Clip . MaxX - Clip . MinX + 1;
  49.  
  50.         if(*Height < Clip . MaxY - Clip . MinY + 1)
  51.             *Height = Clip . MaxY - Clip . MinY + 1;
  52.     }
  53.     else
  54.     {
  55.         *Width    = Screen -> Width;
  56.         *Height    = Screen -> Height;
  57.     }
  58.  
  59.     *Left    = ABS(Screen -> LeftEdge);
  60.     *Top    = ABS(Screen -> TopEdge);
  61.  
  62.     if(*Left > Screen -> Width || *Left < 0)
  63.         *Left = 0;
  64.  
  65.     if(*Top > Screen -> Height || *Top < 0)
  66.         *Top = 0;
  67. }
  68.  
  69.     /* CentreWindow():
  70.      *
  71.      *    Centre a window within the visible bounds of
  72.      *    a screen.
  73.      */
  74.  
  75. STATIC VOID
  76. CentreWindow(struct Screen *Screen,WORD Width,WORD Height,WORD *Left,WORD *Top)
  77. {
  78.     WORD ScreenWidth,ScreenHeight,ScreenLeft,ScreenTop;
  79.  
  80.     GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
  81.  
  82.     *Left    = ScreenLeft + (ScreenWidth - Width) / 2;
  83.     *Top    = ScreenTop + (ScreenHeight - Height) / 2;
  84. }
  85.  
  86. STATIC VOID __saveds __asm
  87. StuffText(REG(a3) LONG *Data,REG(d0) UBYTE Char)
  88. {
  89.     STRPTR                 Buffer    = (STRPTR)Data[0];    // Space allocated for the char buffer
  90.     struct IntuiText    *IText    = (APTR)Data[1];    // Space allocated for the IntuiTexts
  91.  
  92.     if(Char == Data[2] || Char == '\0')
  93.     {
  94.         LONG Width;
  95.  
  96.         IText -> LeftEdge    = 0;
  97.         IText -> TopEdge    = Data[3];    // Text top edge
  98.         IText -> ITextFont    = NULL;
  99.  
  100.             // Line height, derived from font size
  101.  
  102.         Data[3] += Data[4];
  103.  
  104.             // Chop off the rest
  105.  
  106.         *Buffer++ = '\0';
  107.  
  108.             // Measure the length in pixels
  109.  
  110.         if(Data[6])
  111.         {
  112.             Width = TextLength((APTR)Data[6],IText -> IText,(LONG)Buffer - (LONG)IText -> IText - 1);
  113.  
  114.                 // More than we got before?
  115.  
  116.             if(Width > Data[5])
  117.                 Data[5] = Width;
  118.         }
  119.  
  120.         if(Char != '\0')
  121.         {
  122.                 // Link to following text
  123.  
  124.             IText -> NextText = IText + 1;
  125.  
  126.                 // Get ready for the next line
  127.  
  128.             Data[1] = (LONG)(++IText);
  129.  
  130.                 // Start of next line
  131.  
  132.             IText -> IText = Buffer;
  133.         }
  134.         else
  135.             IText -> NextText = NULL;            // Terminate the chain
  136.     }
  137.     else
  138.         *Buffer++ = Char;                        // Just store the character
  139.  
  140.     Data[0] = (LONG)Buffer;                        // Remember for next char
  141. }
  142.  
  143. STATIC VOID __asm
  144. CountChar(REG(a3) LONG *Count,REG(d0) UBYTE Char)
  145. {
  146.     if(Char == Count[2] || Char == '\0')    // Count the number of lines
  147.         Count[1]++;
  148.  
  149.     Count[0]++;                                // Count the number of characters in total
  150. }
  151.  
  152. STATIC struct IntuiText *
  153. BuildITextTable(STRPTR FormatString,va_list VarArgs,UBYTE Terminator,LONG *Information,LONG *MoreData)
  154. {
  155.     struct IntuiText *Primitive;
  156.  
  157.     Information[0] = Information[1] = 0;
  158.     Information[2] = Terminator;
  159.  
  160.     RawDoFmt(FormatString,VarArgs,(VOID (*)())CountChar,Information);
  161.  
  162.     if(Primitive = (struct IntuiText *)AllocVec(Information[1] * sizeof(struct IntuiText) + Information[0],MEMF_ANY))
  163.     {
  164.             // Room for the char buffer
  165.  
  166.         MoreData[0]    = (LONG)(Primitive + Information[1]);
  167.  
  168.             // Room for the IntuiTexts
  169.  
  170.         MoreData[1] = (LONG)Primitive;
  171.  
  172.             // Separator char to use
  173.  
  174.         MoreData[2] = Terminator;
  175.  
  176.             // Top edge of first text, the following lines get placed below
  177.  
  178.         MoreData[3] = 0;
  179.  
  180.             // The maximum width of all lines will end up here
  181.  
  182.         MoreData[5] = 0;
  183.  
  184.             // Now this is important; the first IText buffer must
  185.             // be set up here, the formatting code will do the rest
  186.             // for all the others
  187.  
  188.         Primitive[0].IText = (STRPTR)MoreData[0];
  189.     }
  190.  
  191.     return(Primitive);
  192. }
  193.  
  194.     /* ShowInfo():
  195.      *
  196.      *    Display an EasyRequest like information requester.
  197.      */
  198.  
  199. LONG __stdargs
  200. ShowInfo(struct Window *Parent,STRPTR Title,STRPTR Continue,STRPTR FormatString,...)
  201. {
  202.     struct Screen    *Screen;
  203.     ULONG             IntuiLock;
  204.     LONG             Result = 0;
  205.     BOOL             PopBack;
  206.  
  207.     if(Parent)
  208.         Screen = Parent -> WScreen;
  209.     else
  210.         Screen = LockPubScreen(NULL);
  211.  
  212.     IntuiLock = LockIBase(NULL);
  213.  
  214.     PopBack = (BOOL)(IntuitionBase -> FirstScreen != Screen);
  215.  
  216.     UnlockIBase(IntuiLock);
  217.  
  218.     if(Screen)
  219.     {
  220.         struct DrawInfo *DrawInfo;
  221.  
  222.         if(PopBack)
  223.             ScreenToFront(Screen);
  224.  
  225.         if(DrawInfo = GetScreenDrawInfo(Screen))
  226.         {
  227.             struct TextAttr         FontTemplate;
  228.             va_list                 VarArgs;
  229.             LONG                 Information[3],GadgetInformation[3];
  230.             LONG                 MoreData[7],GadgetData[7];
  231.             struct IntuiText    *BodyText;
  232.             struct IntuiText    *GadgetText;
  233.             struct Gadget        **GadgetTable;
  234.             struct Image        *GadgetFrameImage;
  235.             LONG                 DistX,DistY;
  236.             LONG                 FullButtonWidth;
  237.             struct TextFont        *Font;
  238.             LONG                 RoomX,RoomY;
  239.  
  240.                 // We'll need this one later
  241.  
  242.             Font = DrawInfo->dri_Font;
  243.  
  244.                 // Set up the spacing information
  245.  
  246.             RoomY = (Font->tf_YSize + 1) / 2;
  247.             RoomX = (RoomY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
  248.  
  249.                 // Make a copy of the screen font
  250.  
  251.             AskFont(&Screen->RastPort,&FontTemplate);
  252.  
  253.                 // Request that it be boldfaced, the leftmost
  254.                 // button will receive this type of label
  255.  
  256.             FontTemplate.ta_Style |= FSF_BOLD;
  257.  
  258.             va_start(VarArgs,FormatString);
  259.             BodyText = BuildITextTable(FormatString,VarArgs,'\n',Information,MoreData);
  260.             va_end(VarArgs);
  261.  
  262.             GadgetText = BuildITextTable(Continue,NULL,'|',GadgetInformation,GadgetData);
  263.  
  264.             GadgetTable = (struct Gadget **)AllocVec(sizeof(struct Gadget *) * GadgetInformation[1],MEMF_ANY|MEMF_CLEAR);
  265.  
  266.             GadgetFrameImage = (struct Image *)NewObjectA(NULL,FRAMEICLASS,NULL);
  267.  
  268.             if(GadgetFrameImage && GadgetTable && GadgetText)
  269.             {
  270.                 LONG             ID = 0,Last = GadgetInformation[1] - 1,i;
  271.                 struct Gadget    *Previous = NULL;
  272.                 ULONG             PrevTag = TAG_IGNORE;
  273.  
  274.                     // We'll work with the button sizes in a minute...
  275.  
  276.                 FullButtonWidth = 0;
  277.  
  278.                     // We don't want fonts to be measured
  279.  
  280.                 GadgetData[6] = 0;
  281.  
  282.                 RawDoFmt(Continue,NULL,(VOID (*)())StuffText,GadgetData);
  283.  
  284.                 DistY = 2;
  285.                 DistX = (DistY * DrawInfo->dri_Resolution.Y) / DrawInfo->dri_Resolution.X;
  286.  
  287.                 GadgetText[0].ITextFont = &FontTemplate;
  288.  
  289.                 for(i = 0 ; i <= Last ; i++)
  290.                 {
  291.                     if(i == Last)
  292.                         ID = 0;
  293.                     else
  294.                         ID++;
  295.  
  296.                     GadgetText[i].NextText = NULL;
  297.  
  298.                     if(GadgetTable[i] = NewObject(NULL,FRBUTTONCLASS,
  299.                         GA_IntuiText,    &GadgetText[i],
  300.                         GA_Image,        GadgetFrameImage,
  301.                         GA_RelVerify,    TRUE,
  302.                         GA_ID,            ID,
  303.                         GA_DrawInfo,    DrawInfo,
  304.                         PrevTag,        Previous,
  305.                     TAG_DONE))
  306.                     {
  307.                         Previous    = GadgetTable[i];
  308.                         PrevTag        = GA_Previous;
  309.  
  310.                         SetAttrs(Previous,
  311.                             GA_Width,    2*DistX + Previous->Width,
  312.                             GA_Height,    2*DistY + Previous->Height,
  313.                             GA_DrawInfo,DrawInfo,
  314.                         TAG_DONE);
  315.  
  316.                             // Add the width of the button, plus
  317.                             // some room in between
  318.  
  319.                         FullButtonWidth += Previous->Width + RoomX;
  320.                     }
  321.                     else
  322.                     {
  323.                         LONG j;
  324.  
  325.                         for(j = 0 ; j < i ; j++)
  326.                             DisposeObject(GadgetTable[i]);
  327.  
  328.                         FreeVec(GadgetTable);
  329.                         GadgetTable = NULL;
  330.  
  331.                         break;
  332.                     }
  333.                 }
  334.  
  335.                     // Subtract the trailing space, add the border space
  336.  
  337.                 FullButtonWidth += Screen->WBorRight + RoomX + Screen->WBorLeft;
  338.             }
  339.  
  340.                 // Did we get what we wanted and will the buttons fit on
  341.                 // the screen?
  342.  
  343.             if(BodyText && GadgetText && GadgetTable && FullButtonWidth <= Screen->Width)
  344.             {
  345.                 WORD                Width,Height,Left,Top;
  346.  
  347.                 WORD                WindowWidth,WindowHeight,
  348.                                     ScreenWidth,ScreenHeight,
  349.                                     ScreenLeft,ScreenTop;
  350.  
  351.                 struct Image        *FillImage,
  352.                                     *FrameImage,
  353.                                     *TextImage;
  354.  
  355.                 LONG                FullTitleWidth;
  356.  
  357.                 ULONG                 DepthWidth;
  358.                 struct Image        *DepthImage;
  359.  
  360.                     // Before we do anything else, set up the
  361.                     // full width of the window title; this includes
  362.                     // both the text and the depth arrangement gadget
  363.  
  364.                 if(Title)
  365.                     FullTitleWidth = TextLength(&Screen->RastPort,Title,strlen(Title));
  366.                 else
  367.                     FullTitleWidth = 0;
  368.  
  369.                     // Get the width of the window depth gadget for this screen
  370.  
  371.                 if(DepthImage = NewObject(NULL,SYSICLASS,
  372.                     SYSIA_Size,        (Screen->Flags & SCREENHIRES) ? SYSISIZE_MEDRES : SYSISIZE_LOWRES,
  373.                     SYSIA_Which,    DEPTHIMAGE,
  374.                     SYSIA_DrawInfo,    DrawInfo,
  375.                 TAG_DONE))
  376.                 {
  377.                     GetAttr(IA_Width,DepthImage,&DepthWidth);
  378.  
  379.                     DisposeObject(DepthImage);
  380.                 }
  381.                 else
  382.                     DepthWidth = (Screen->Flags & SCREENHIRES) ? 23 : 17;
  383.  
  384.                 FullTitleWidth += DepthWidth + 2;
  385.  
  386.                 if(FullTitleWidth > Screen -> Width)
  387.                     FullTitleWidth = Screen -> Width;
  388.  
  389.                     // Increase the size to fit all the buttons into the window
  390.  
  391.                 if(FullButtonWidth > FullTitleWidth)
  392.                     FullTitleWidth = FullButtonWidth;
  393.  
  394.                     // Height of each line
  395.  
  396.                 MoreData[4] = Font->tf_YSize;
  397.  
  398.                     // Pointer to screen rastport used for measuring the text
  399.  
  400.                 MoreData[6] = (LONG)&Screen->RastPort;
  401.  
  402.                     // Now do the magic formatting...
  403.  
  404.                 va_start(VarArgs,FormatString);
  405.                 RawDoFmt(FormatString,VarArgs,(VOID (*)())StuffText,MoreData);
  406.                 va_end(VarArgs);
  407.  
  408.                     // The maximum width of all lines is now in MoreData[5],
  409.                     // the effective height of the block in MoreData[3];
  410.  
  411.                 TextImage = NewObject(NULL,ITEXTICLASS,
  412.                     IA_FGPen,        DrawInfo->dri_Pens[TEXTPEN],
  413.                     IA_Data,        BodyText,
  414.                     IA_Width,        MoreData[5] + 2*DistX,    // Add a little room around the text
  415.                     IA_Height,        MoreData[3] + 2*DistY,
  416.                 TAG_DONE);
  417.  
  418.                     // Build the checkered background fill pattern
  419.  
  420.                 FillImage = NewObject(NULL,FILLRECTCLASS,
  421.                     IA_APattern,    &Crosshatch,
  422.                     IA_APatSize,    1,
  423.                     IA_Mode,        JAM2,
  424.                     IA_FGPen,        DrawInfo->dri_Pens[SHINEPEN],
  425.                     IA_BGPen,        DrawInfo->dri_Pens[BACKGROUNDPEN],
  426.                 TAG_DONE);
  427.  
  428.                     // Do the same for the frame around the text
  429.  
  430.                 FrameImage = NewObject(NULL,FRAMEICLASS,
  431.                     IA_Recessed,    TRUE,
  432.                 TAG_DONE);
  433.  
  434.                     // Did we get 'em all?
  435.  
  436.                 if(FillImage && FrameImage && TextImage)
  437.                 {
  438.                     struct Gadget     Dummy;
  439.                     struct IBox         FramedSize;
  440.                     LONG             WindowLeft,
  441.                                      WindowTop;
  442.                     struct Window    *Window;
  443.  
  444.                         // We'll need these offsets pretty soon
  445.  
  446.                     WindowLeft    = Screen->WBorLeft;
  447.                     WindowTop    = Screen->WBorTop + Screen->Font->ta_YSize + 1;
  448.  
  449.                         // Now check how large the surrounding frame would be
  450.  
  451.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
  452.  
  453.                         // Pad the space around the frame a bit
  454.  
  455.                     FramedSize.Width    += 2 * RoomX;
  456.                     FramedSize.Height    += 2 * RoomY;
  457.  
  458.                         // Save these for the window open stuff
  459.  
  460.                     Width    = WindowLeft +    FramedSize.Width +    Screen->WBorRight;
  461.                     Height    = WindowTop +    FramedSize.Height +    Screen->WBorBottom;
  462.  
  463.                         // If the window title won't fit on the screen,
  464.                         // expand the fillimage a bit; do the same to the
  465.                         // textimage.
  466.  
  467.                     if(Width < FullTitleWidth)
  468.                     {
  469.                         LONG Adapt = (FullTitleWidth - Width + 1) & ~1;
  470.  
  471.                         FramedSize.Width    += Adapt;
  472.                         Width                += Adapt;
  473.  
  474.                         DistX                += Adapt / 2;
  475.  
  476.                         SetAttrs((Object *)TextImage,
  477.                             IA_Width,MoreData[5] + 2*DistX,
  478.                         TAG_DONE);
  479.                     }
  480.  
  481.                         // Adjust size and position of the background pattern
  482.  
  483.                     SetAttrs((Object *)FillImage,
  484.                         IA_Left,    WindowLeft,
  485.                         IA_Top,        WindowTop,
  486.                         IA_Width,    FramedSize.Width,
  487.                         IA_Height,    FramedSize.Height,
  488.                     TAG_DONE);
  489.  
  490.                         // Do the whole thing all over again for the framed text;
  491.                         // this will put the right coords to centre the text within
  492.                         // the frame into FramedSize
  493.  
  494.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,FRAMEF_SPECIFY);
  495.  
  496.                         // Move the text around
  497.  
  498.                     SetAttrs((Object *)TextImage,
  499.                         IA_Left,    WindowLeft    - FramedSize.Left    + DistX,
  500.                         IA_Top,        WindowTop    - FramedSize.Top    + DistY,
  501.                     TAG_DONE);
  502.  
  503.                         // Almost finished, now centre the frame around the text
  504.  
  505.                     DoMethod((Object *)FrameImage,IM_FRAMEBOX,&TextImage->LeftEdge,&FramedSize,DrawInfo,NULL);
  506.  
  507.                     SetAttrs((Object *)FrameImage,
  508.                         IA_Left,    FramedSize.Left        - DistX,
  509.                         IA_Top,        FramedSize.Top        - DistY,
  510.                         IA_Width,    FramedSize.Width,
  511.                         IA_Height,    FramedSize.Height,
  512.                     TAG_DONE);
  513.  
  514.                         // Now link the objects together
  515.  
  516.                     FillImage->NextImage    = FrameImage;
  517.                     FrameImage->NextImage    = TextImage;
  518.  
  519.                         // Zap the dummy gadget and put the image inside
  520.  
  521.                     memset(&Dummy,0,sizeof(Dummy));
  522.  
  523.                     Dummy.Flags            = GFLG_GADGIMAGE|GFLG_GADGHNONE;
  524.                     Dummy.GadgetRender    = FillImage;
  525.  
  526.                         // Put the gadget in
  527.  
  528.                     /* ALWAYS */
  529.                     {
  530.                         LONG    Left    = FrameImage->LeftEdge,
  531.                                 Top        = FillImage->TopEdge + FillImage->Height;
  532.  
  533.                         GadgetTable[GadgetInformation[1] - 1]->NextGadget = &Dummy;
  534.  
  535.                         SetAttrs((Object *)FillImage,
  536.                             IA_Height,    FillImage->Height + GadgetTable[0]->Height + RoomY,
  537.                         TAG_DONE);
  538.  
  539.                         Height += GadgetTable[0]->Height + RoomY;
  540.  
  541.                         if(GadgetInformation[1] > 1)
  542.                         {
  543.                             LONG Room = Width - FullButtonWidth,Count = GadgetInformation[1] - 1,i;
  544.  
  545.                             Left     = FrameImage->LeftEdge;
  546.                             Room    += Count * RoomX;
  547.  
  548.                             for(i = 0 ; i <= Count ; i++)
  549.                             {
  550.                                 SetAttrs((Object *)GadgetTable[i],
  551.                                     GA_Top,        Top,
  552.                                     GA_Left,    Left,
  553.                                 TAG_DONE);
  554.  
  555.                                 Left += GadgetTable[i]->Width + ((Room * (i + 1)) / Count - (Room * i) / Count);
  556.                             }
  557.                         }
  558.                         else
  559.                         {
  560.                             SetAttrs((Object *)GadgetTable[0],
  561.                                 GA_Top,        Top,
  562.                                 GA_Left,    Left + (FillImage->Width - GadgetTable[0]->Width) / 2,
  563.                             TAG_DONE);
  564.                         }
  565.                     }
  566.  
  567.                         // Check if the window will fit on the screen
  568.  
  569.                     if(Width <= Screen->Width && Height <= Screen->Height)
  570.                     {
  571.                             // Centre the body text strings
  572.  
  573.                         /* ALWAYS */
  574.                         {
  575.                             struct IntuiText *This;
  576.  
  577.                             for(This = BodyText ; This ; This = This->NextText)
  578.                             {
  579.                                 This->ITextFont = Screen->Font;
  580.                                 This->LeftEdge = (MoreData[5] - IntuiTextLength(This)) / 2;
  581.                                 This->ITextFont = NULL;
  582.                             }
  583.                         }
  584.  
  585.                             // Centre the window to open
  586.  
  587.                         if(Parent)
  588.                         {
  589.                             WindowLeft        = Parent -> LeftEdge + Parent -> BorderLeft;
  590.                             WindowTop        = Parent -> TopEdge + Parent -> BorderTop;
  591.                             WindowWidth        = Parent -> Width - (Parent -> BorderLeft + Parent -> BorderRight);
  592.                             WindowHeight    = Parent -> Height - (Parent ->BorderTop + Parent -> BorderBottom);
  593.  
  594.                             if((Left = WindowLeft + (WindowWidth - Width) / 2) < 0)
  595.                                 Left = 0;
  596.  
  597.                             if((Top = WindowTop + (WindowHeight - Height) / 2) < 0)
  598.                                 Top = 0;
  599.  
  600.                             GetScreenInfo(Screen,&ScreenLeft,&ScreenTop,&ScreenWidth,&ScreenHeight);
  601.  
  602.                             if(Left < ScreenLeft || Left + Width > ScreenLeft + ScreenWidth)
  603.                                 Left = -1;
  604.  
  605.                             if(Top < ScreenTop || Top + Height > ScreenTop + ScreenHeight)
  606.                                 Top = -1;
  607.  
  608.                             if(Top == -1 || Left == -1)
  609.                                 CentreWindow(Screen,Width,Height,&Left,&Top);
  610.                         }
  611.                         else
  612.                             CentreWindow(Screen,Width,Height,&Left,&Top);
  613.  
  614.                             // Finally, open the window
  615.  
  616.                         if(Window = OpenWindowTags(NULL,
  617.                             WA_Left,            Left,
  618.                             WA_Top,                Top,
  619.                             WA_Width,            Width,
  620.                             WA_Height,            Height,
  621.                             WA_Title,            Title,
  622.                             WA_Flags,            WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_RMBTRAP | WFLG_NOCAREREFRESH | WFLG_SIMPLE_REFRESH | WFLG_ACTIVATE,
  623.                             WA_IDCMP,            IDCMP_GADGETUP | IDCMP_VANILLAKEY | IDCMP_RAWKEY,
  624.                             WA_CustomScreen,    Screen,
  625.                             WA_Gadgets,            GadgetTable[0],
  626.                         TAG_DONE))
  627.                         {
  628.                             struct IntuiMessage    *Message;
  629.                             struct Gadget        *MsgGadget;
  630.                             ULONG                 MsgClass;
  631.                             LONG                 MsgCode;
  632.                             struct Gadget        *Gadget        = NULL;
  633.                             BOOL                 Terminated    = FALSE;
  634.  
  635.                             do
  636.                             {
  637.                                 WaitPort(Window->UserPort);
  638.  
  639.                                 while(Message = (struct IntuiMessage *)GetMsg(Window->UserPort))
  640.                                 {
  641.                                     MsgClass    = Message->Class;
  642.                                     MsgCode        = Message->Code;
  643.                                     MsgGadget    = Message->IAddress;
  644.  
  645.                                     ReplyMsg((struct Message *)Message);
  646.  
  647.                                     switch(MsgClass)
  648.                                     {
  649.                                         case IDCMP_GADGETUP:
  650.  
  651.                                             Terminated    = TRUE;
  652.                                             Result        = MsgGadget->GadgetID;
  653.  
  654.                                             break;
  655.  
  656.                                         case IDCMP_VANILLAKEY:
  657.  
  658.                                             MsgCode = ToUpper(MsgCode);
  659.  
  660.                                             switch(MsgCode)
  661.                                             {
  662.                                                 case '\033':
  663.                                                 case 'B':
  664.                                                 case ('C' & 0x1F):
  665.  
  666.                                                     Terminated    = TRUE;
  667.                                                     Gadget        = GadgetTable[GadgetInformation[1] - 1];
  668.  
  669.                                                     break;
  670.  
  671.                                                 case '\r':
  672.                                                 case 'V':
  673.  
  674.                                                     Terminated    = TRUE;
  675.                                                     Gadget        = GadgetTable[0];
  676.  
  677.                                                     break;
  678.                                             }
  679.  
  680.                                             break;
  681.  
  682.                                         case IDCMP_RAWKEY:
  683.  
  684.                                             switch(MsgCode)
  685.                                             {
  686.                                                 case HELP_CODE:
  687.  
  688.                                                     GuideDisplay(CONTEXT_MAIN);
  689.                                                     break;
  690.  
  691.                                                 default:
  692.  
  693.                                                     if(MsgCode >= F01_CODE && MsgCode <= F10_CODE)
  694.                                                     {
  695.                                                         MsgCode -= F01_CODE;
  696.  
  697.                                                         if(MsgCode < GadgetInformation[1])
  698.                                                         {
  699.                                                             Terminated = TRUE;
  700.  
  701.                                                             Gadget = GadgetTable[MsgCode];
  702.                                                         }
  703.                                                     }
  704.  
  705.                                                     break;
  706.                                             }
  707.  
  708.                                             break;
  709.                                     }
  710.                                 }
  711.                             }
  712.                             while(!Terminated);
  713.  
  714.                             if(Gadget)
  715.                             {
  716.                                 STATIC ULONG SelectedTags[]        = { GA_Selected,TRUE,    TAG_DONE };
  717.                                 STATIC ULONG DeselectedTags[]    = { GA_Selected,FALSE,    TAG_DONE };
  718.  
  719.                                 SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)SelectedTags);
  720.                                 RefreshGList(Gadget,Window,NULL,1);
  721.  
  722.                                 DelayTime(0,80000);
  723.  
  724.                                 SetGadgetAttrsA(Gadget,Window,NULL,(struct TagItem *)DeselectedTags);
  725.                                 RefreshGList(Gadget,Window,NULL,1);
  726.                             }
  727.  
  728.                             CloseWindow(Window);
  729.                         }
  730.                     }
  731.                 }
  732.  
  733.                     // Get rid of the images
  734.  
  735.                 DisposeObject(FillImage);
  736.                 DisposeObject(FrameImage);
  737.                 DisposeObject(TextImage);
  738.             }
  739.  
  740.                 // And the buffers so much work went into...
  741.  
  742.             FreeVec(BodyText);
  743.             FreeVec(GadgetText);
  744.  
  745.             if(GadgetTable)
  746.             {
  747.                 LONG i;
  748.  
  749.                 for(i = 0 ; i < GadgetInformation[1] ; i++)
  750.                     DisposeObject(GadgetTable[i]);
  751.  
  752.                 FreeVec(GadgetTable);
  753.             }
  754.  
  755.             DisposeObject(GadgetFrameImage);
  756.  
  757.             FreeScreenDrawInfo(Screen,DrawInfo);
  758.         }
  759.  
  760.         if(PopBack)
  761.             ScreenToBack(Screen);
  762.  
  763.         if(!Parent)
  764.             UnlockPubScreen(NULL,Screen);
  765.     }
  766.  
  767.     return(Result);
  768. }
  769.